
const ftp = require('ftp');//连接FTP
const path = require('path');
const client = new ftp();
const _ftpclient = new ftp();
const fs = require('fs');
import { deleteFile } from "./fileUtil";

//本地文件夹路径；
//const localDirPath = '/test/';
//远程地址，打开ftp以后的地址，不需要加入host；
let remotePath = '/data/docker/vsftp/admin/';

/**
 * ftp 配置文件
 */
const connectionProperties = {
    host: '192.168.1.200',                       //ftp地址；
    user: 'admin',                       //用户名；
    password: '123456',                   //密码；
    port: 21                        //端口；
};

/**
 *  连接FTP
 * @param {*} obj 默认内部配置文件
 * @param {*} cb  回调函数
 * @returns 
 */
let connection = async function (obj = connectionProperties, rePath = '') {
    console.log(rePath)

    //try {
    let connection = await new Promise((resolve, reject) => {
        if (rePath && rePath.length > 0) {
            if (!rePath.endsWith('/')) { rePath = rePath + '/' }
            remotePath = rePath;
            console.log(remotePath)
        }
        if (obj == null || obj == undefined) {
            obj = connectionProperties;
        }

        let params = Object.assign({}, obj);
        // 连接成功
        _ftpclient.on('ready', function () {
            console.log('连接成功')

            setTimeout(() => {
                if (_ftpclient.connected) {
                    _ftpclient.end();
                }
            }, 1000);
            resolve('0');
        });
        // 连接错误
        _ftpclient.on('error', function (err) {
            console.log('连接错误', err)
            reject(err);
        })
        // 会话保持时间
        // params.keepalive = 1000;
        // 开启连接
        _ftpclient.connect(params);
    });
    return connection;
    // } catch (error) {
    //     console.log('连接成功', error)
    // }

}

let close = function () {
    if (client != null) {
        client.end();
    }
}


/**
 * 文件转成相应单位大小
 * @param {*} size 
 * @returns 
 */
function sizeTostr(size) {
    var data = "";
    if (size < 0.1 * 1024) { //如果小于0.1KB转化成B  
        data = size.toFixed(2) + "B";
    } else if (size < 0.1 * 1024 * 1024) {//如果小于0.1MB转化成KB  
        data = (size / 1024).toFixed(2) + "KB";
    } else if (size < 0.1 * 1024 * 1024 * 1024) { //如果小于0.1GB转化成MB  
        data = (size / (1024 * 1024)).toFixed(2) + "MB";
    } else { //其他转化成GB  
        data = (size / (1024 * 1024 * 1024)).toFixed(2) + "GB";
    }
    var sizestr = data + "";
    var len = sizestr.indexOf("\.");
    var dec = sizestr.substr(len + 1, 2);
    if (dec == "00") {//当小数点后为00时 去掉小数部分  
        return sizestr.substring(0, len) + sizestr.substr(len + 3, 2);
    }
    return sizestr;
}


/**
 * 切换目录
 * @param {*} dirpath  目录路径
 * @returns 
 */
async function cwd(dirpath) {
    return new Promise((resolve, reject) => {
        client.cwd(dirpath, (err, dir) => {
            resolve({ err: err, dir: dir });
        })
    });
}

/**
 * 获取当前目录层级
 * @param {*} cb  回调函数
 * @returns 
 */
let pwd = async function (cb) {
    return new Promise((resolve, reject) => {
        client.pwd(function (err, dir) {
            console.log(dir)
            if (err) reject(err);
            resolve(dir);
        })
    });
}



//列出目标目录
async function list(dirpath) {
    if (dirpath != undefined) {
        let { err: ea, dir } = await cwd(dirpath);//此处应对err做处理
    }
    return new Promise((resolve, reject) => {
        client.list((err, files) => {
            console.log("files", files)

            if (files != undefined) {
                files.map(item => {
                    item.name = Buffer.from(item.name, 'binary').toString('utf8')
                    // item.name = Buffer.from(item.name, 'binary').toString('utf8') // 若设置了传输数据类型为ASCII
                })
            }
            resolve({ err: err, files: files })
        })
    });
}

//下载文件
async function download(filePath, savePath) {
    const dirpath = path.dirname(filePath);
    const fileName = path.basename(filePath);
    return new Promise((resolve, reject) => {
        client.get(fileName, true, (err, rs) => {
            let ws = fs.createWriteStream(savePath + '/' + fileName);
            if (rs != undefined && rs) {
                rs.pipe(ws);
            }

            resolve({ err: err });
        });
    });
}


/**
 *  独立连接下载
 * @param {*} connectionProperties  ftp 服务器配置
 * @param {*} filePath  服务器下载路径
 * @param {*} savePath  保存本地路径
 */
async function downloadSingle(connectionProperties, filePath, savePath) {
    // const fileName = path.basename(filePath);
    return new Promise((resolve, reject) => {
        var c = new ftp();
        c.on('ready', function () {
            c.get(filePath, function (err, stream) {
                if (err) throw err;
                stream.once('close', function () { c.end(); });
                stream.pipe(fs.createWriteStream(savePath));
                resolve({ err: err });
                console.log("下载完成路径：", savePath);
            });
        });
        // connect to localhost:21 as anonymous
        c.connect(connectionProperties);
    });
}




/**
 * 批量上传文件 -包含文件目录
 * @param {*} ftpConfig 服务器配置
 * @param {*} localDirPath  本都目录 
 * @param {*} remotePath  远程文件路径
 */
const uploadFiles = function (ftpConfig, localDirPath, remotePath, fileexts, callback) {
    // 创建 FTP 客户端实例
    // let
    // if (_client == null)
    const _client = new ftp();

    /**
     * 递归上传目录
     * @param {*} localPath  本地路径
     * @param {*} remotePath 远程路径
     * @param {*} callback   回调函数
     */
    function uploadDirectory(localPath, remotePath, fileexts, func) {

        fs.readdir(localPath, (err, files) => {
            if (err) {
                throw err;
            }
            let count = files.length;
            console.log(_client)
            if (!_client.connected) {
                _client.connect(ftpConfig);
            }

            files.forEach((file) => {
                const localFile = `${localPath}/${file}`;
                let remoteFile = `${remotePath}/${file}`;
                // 限制某些后缀才能传
                var extname = path.extname(localFile)
                if (extname && fileexts && fileexts != undefined && fileexts.length > 0 && !fileexts.indexOf(extname.substring(1))) {
                    return;
                }
                //arc/a/b
                //arc/a/b/arc/a/b
                fs.stat(localFile, (err, stats) => {
                    if (err) { throw err; }
                    if (stats.isFile()) {
                        // 503 Bad sequence of commands  需要先进行cwd 否者会有异常出现
                        _client.cwd(remotePath, (pwdErr, cwd) => {
                            if (pwdErr) {
                                console.log(`cwd失败->: ${remoteFile}`);
                            } else {
                                // 上传文件
                                _client.put(localFile, remoteFile, false, (err) => {
                                    if (err) {
                                        console.log("文件上传失败->", err);
                                    }
                                    //console.log(`Uploaded: ${localFile}`);
                                    count--;
                                    if (count <= 0) { _client.end(); }
                                    func(localFile);
                                    _client.cwd(remotePath, (pwdErr, cwd) => {
                                        if (pwdErr) {
                                            console.log(`cwd失败->: ${remoteFile}`);
                                        }
                                    });
                                });
                            }
                        })

                    } else if (stats.isDirectory()) {
                        // 创建目录并递归上传
                        _client.mkdir(remoteFile, true, (err) => {
                            if (err) { throw err; }
                            // console.log(`Created directory: ${remoteFile}`);
                            uploadDirectory(localFile, remoteFile, fileexts, func);
                        });
                    }
                });
            });
        });
    }

    console.log("当 FTP 客户端连接成功后", _client)
    // 当 FTP 客户端连接成功后
    _client.on('ready', () => {
        // 创建目录并递归上传
        _client.mkdir(remotePath, true, (err) => {
            _client.cwd(remotePath, (pwdErr, cwd) => {
                if (pwdErr) {
                    console.error("pwdErr", pwdErr)
                } else {
                    // 递归上传目录
                    setTimeout(() => {
                        uploadDirectory(localDirPath, remotePath, fileexts, (c) => {
                            callback(c);
                        });
                    }, 1000)
                }
            })

        });

    });

    // 连接到 FTP 服务器
    ftpConfig['keepalive'] = 1000;
    ftpConfig['_ending'] = 'utf8';
    ftpConfig['pasvTimeout'] = 1000;
    _client.connect(ftpConfig);
    _client.on('error', callback);
}

/**
 * 批量上传文件 -包含文件目录
 * @param {*} ftpConfig 服务器配置
 * @param {*} localDirPath  本都目录 
 * @param {*} remotePath  远程文件路径
 */
const uploadFiles2 = async function (ftpConfig, localDirPath, remotePath, fileexts, callback) {
    // 创建 FTP 客户端实例
    const _client = new ftp();
    /**
     * 递归上传目录
     * @param {*} localPath  本地路径
     * @param {*} remotePath 远程路径
     * @param {*} callback   回调函数
     */
    async function uploadDirectory(localPath, remotePath, fileexts, func) {

        fs.readdir(localPath, (err, files) => {
            if (err) {
                throw err;
            }

            let count = files.length;
            if (count == 0) {
                return _client.end();;
            }
            files.forEach((file) => {
                const localFile = `${localPath}/${file}`;
                let remoteFile = `${remotePath}/${file}`;
                // 限制某些后缀才能传
                var extname = path.extname(localFile)
                if (extname && fileexts && fileexts != undefined && fileexts.length > 0 && !fileexts.indexOf(extname.substring(1))) {
                    return;
                }


                fs.stat(localFile, (err, stats) => {
                    if (err) { throw err; }
                    if (stats.isFile()) {
                        // 上传文件
                        _client.put(localFile, remoteFile, (err) => {
                            if (err) { throw err; }
                            //console.log(`Uploaded: ${localFile}`);
                            count--;
                            if (count === 0) { _client.end(); }
                            func({ count: count, filePath: localFile });
                        });
                    } else if (stats.isDirectory()) {
                        // console.log("remoteFile", remoteFile)
                        // 创建目录并递归上传
                        _client.mkdir(remoteFile, true, (err) => {
                            if (err) { throw err; }
                            //console.log(`Created directory: ${remoteFile}`);
                            uploadDirectory(localFile, remoteFile, fileexts, func);
                        });
                    }
                });
            });
        });
    }

    // 连接到 FTP 服务器
    return await new Promise((resolve, reject) => {
        // 当 FTP 客户端连接成功后
        _client.on('ready', () => {
            // 创建目录并递归上传
            _client.mkdir(remotePath, true, (err) => {
                _client.cwd(remotePath, (pwdErr, cwd) => {
                    if (pwdErr) {
                        console.error("pwdErr", pwdErr)
                    } else {
                        // 递归上传目录
                        uploadDirectory(localDirPath, remotePath, fileexts, (c) => {
                            callback(c);
                            if (c & c.count == 0) {
                                _client.end();
                                resolve(c);
                            }
                        });
                    }
                })

            });

        });
        // 连接到 FTP 服务器
        _client.connect(ftpConfig);
        _client.on('error', reject);
    });


}

/**
 *  递归下载文件
 * @param {*} ftpConfig 
 * @param {*} remoteDirectory 
 * @param {*} localDrectory 
 * @param {*} that 
 */
async function downloadRecursive(ftpConfig, remoteDirectory, localDrectory, that) {
    // 创建FTP连接
    var _ftp = new ftp();
    var filecount = 0;
    // 递归下载函数
    async function downloadFile(_ftp, remotePath, localPath) {
		return new Promise((resolve, reject) => {
			_ftp.list(remotePath, (err, files) => {
				var count = 0;
				if (files == undefined || err) {
					_ftp.end();
					return false;
				}
				count = files.length;
				if (count == 0) {
					_ftp.end();
					return false;
				}
				if (!_ftp.connected) {
					_ftp.connect(ftpConfig);
				}
				for (let file of files) {
					var filename = Buffer.from(file.name, 'binary').toString('utf8')
					const remoteFilePath = remotePath + '/' + filename;
					const localFilePath = localPath + '/' + filename;
					if (file.type === 'd') {
						// 如果是目录，则递归下载目录下的文件
						fs.mkdirSync(localFilePath, { recursive: true });
						downloadFile(_ftp, remoteFilePath, localFilePath);
					} else {
						downloadSingle(ftpConfig, remoteFilePath, localFilePath).then(() => {
							count--;
							console.log(count)
							if (count <= 0) {
								setTimeout(() => {
									_ftp.end();
								}, 6000 * 5)
							}
						});


					}
				}
			});
		});

    }


    // async function loopFile(_ftp, remoteDirectory) {
    //     _ftp.list(remoteDirectory, async (err, files) => {
    //         if (files) {
    //             for (let file of files) {
    //                 var filename = Buffer.from(file.name, 'binary').toString('utf8')
    //                 const remoteFilePath = remoteDirectory + '/' + filename;
    //                 if (file.type === 'd') {
    //                     loopFile(_ftp, remoteFilePath);
    //                 } else {
    //                     console.log("filecount->", filecount)
    //                     filecount++;
    //                 }
    //             }
    //         }
    //     });
    // }


    await new Promise((resolve, reject) => {
        _ftp.connect(ftpConfig);
        _ftp.on('ready', async () => {
            console.log('Connected to FTP server');
            //await loopFile(_ftp, remoteDirectory);
            console.log("count222->", filecount)
            // 指定远程目录和本地目录
            // 开始递归下载
            await downloadFile(_ftp, remoteDirectory, localDrectory);
        });
        _ftp.on('error', reject);
    });

}



/**
 * 并发下载函数-适合多文件
 * @param {*} ftpConfig  ftp 服务器配置
 * @param {*} files   需要下载的文件
 * @param {*} savePath   保存下载的文件
 */
async function downloadFiles(ftpConfig, files) {
    const _ftp = new ftp();
    // 单个文件下载函数
    async function downloadFile(_ftp, file) {
        return new Promise((resolve, reject) => {
            // 创建可写流，将文件写入本地
            const writeStream = fs.createWriteStream(file.localPath);

            // 下载文件
            _ftp.get(file.remotePath, (err, stream) => {
                if (err) {
                    reject(err);
                    return;
                }

                // 监听传输完成事件
                stream.once('close', resolve);
                stream.once('error', reject);

                // 将文件流导向可写流
                stream.pipe(writeStream);
            });
        });
    }

    // 连接到 FTP 服务器
    await new Promise((resolve, reject) => {
        _ftp.connect(ftpConfig);
        _ftp.on('ready', resolve);
        _ftp.on('error', reject);
    });

    // 并发下载文件
    await Promise.all(
        files.map(file => downloadFile(_ftp, file))
    );
    // 断开连接
    _ftp.end();
}

// 启动并发下载

//    let  files=[{
//     remotePath: rePath + _path.sep + url,
//     localPath: savePath + _path.sep + url,
//   }]
// downloadFiles(files).then(() => {
//         console.log('文件下载完成');
// }).catch(err => {
//    console.error('文件下载出错:', err);
//});



/**
 * 并发上传文件函数
 * @param {*} ftpConfig  ftp 服务器配置
 * @param {*} localFilePath   本地待上传文件
 * @param {*} remoteFilePath   保存远程的文件
 */
async function uploadSingleFiles(ftpConfig, localFilePath, remoteFilePath, originalName = true) {
    const _ftp = new ftp();
    // 单个文件上传函数
    async function uploadFile(localFilePath, remoteFilePath, originalName) {
        return new Promise((resolve, reject) => {
            if (originalName) {
                remoteFilePath = remoteFilePath + "/" + path.basename(localFilePath);
            }

            // 上传文件
            _ftp.put(localFilePath, remoteFilePath, err => {
                if (err) {
                    console.error(err);
                    reject(err);
                    return;
                } else {
                    resolve(0);
                }
                // 断开连接
                _ftp.end();
            });

        });
    }

    // 连接到 FTP 服务器
    await new Promise((resolve, reject) => {
        _ftp.connect(ftpConfig);
        _ftp.on('ready', () => {
            let dirpath = remoteFilePath;
            if (remoteFilePath.indexOf(".") > -1) {
                dirpath = path.dirname(remoteFilePath);
            }
            // 删除目录
            //_ftp.e(dirPath, true);
            _ftp.mkdir(dirpath, true, (err) => {
                if (err) {
                    console.log('mkdir' + remoteFilePath + 'err', err);
                    return;
                }
            });

            uploadFile(localFilePath, remoteFilePath, originalName).then((r) => {
                resolve(r)
            });

        });

        _ftp.on('error', (err) => {
            console.log("ftp 连接异常==>", err)

            reject
        });

    });

    // _ftp.mkdir(remoteFilePath, true, (err) => {
    //     if (err) {
    //         console.log('mkdir' + remoteFilePath + 'err', err);
    //         return;
    //     }
    //     console.log('mkdir ' + remoteFilePath + '  success');
    // });



}
/**
 * 并发上传文件函数
 * @param {*} ftpConfig  ftp 服务器配置
 * @param {*} localFilePath   本地待上传文件
 * @param {*} remoteFilePath   保存远程的文件
 */
async function uploadSingleFile(ftpConfig, localFilePath, remoteFilePath, delFile = false, originalName = true) {
    const _ftp = new ftp();
    // 单个文件上传函数
    async function uploadFile(localFilePath, remoteFilePath, originalName) {
        return new Promise((resolve, reject) => {
            if (originalName) {
                remoteFilePath = remoteFilePath + "/" + path.basename(localFilePath);
            }

            // 上传文件
            _ftp.put(localFilePath, remoteFilePath, err => {
                if (err) {
                    console.error(err);
                    // 断开连接
                    reject(err);
                } else {
                    // 断开连接
                    resolve(0);
                }
                _ftp.end();
                if (delFile) {
                    deleteFile(localFilePath)
                }
            });

        });
    }

    // 连接到 FTP 服务器
    await new Promise((resolve, reject) => {
        _ftp.connect(ftpConfig);
        _ftp.on('ready', () => {
            let dirpath = remoteFilePath;
            if (remoteFilePath.indexOf(".") > -1) {
                dirpath = path.dirname(remoteFilePath);
            }
            // 删除目录
            //_ftp.e(dirPath, true);
            _ftp.mkdir(dirpath, true, (err) => {
                if (err) {
                    console.log('mkdir' + remoteFilePath + 'err', err);
                    return;
                }
            });

            uploadFile(localFilePath, remoteFilePath, originalName).then((r) => {
                resolve(r)
            });

        });

        _ftp.on('error', (err) => {
            console.log("ftp 连接异常==>", err)

            reject(err)
        });

    });

    // _ftp.mkdir(remoteFilePath, true, (err) => {
    //     if (err) {
    //         console.log('mkdir' + remoteFilePath + 'err', err);
    //         return;
    //     }
    //     console.log('mkdir ' + remoteFilePath + '  success');
    // });



}


/**
 * 递归删除文件夹和文件
 * @param {*} ftpConfig  ftp配置
 * @param {*} remotePath  远程文件夹
 */
async function deleteFolderAndFiles(ftpConfig, remotePath) {
    const _ftp = new ftp();

    let deleteFileAndDir = (remotePath) => {
        // 获取文件夹和文件列表
        _ftp.list(remotePath, (err, list) => {
            if (err) {

                //   console.error('获取文件列表出错：', err);
                return;
            }

            // 遍历列表
            list.forEach(item => {
                var filename = Buffer.from(item.name, 'binary').toString('utf8')
                const itemPath = remotePath + '/' + filename;
                // 如果是文件夹，递归删除
                if (item.type === 'd') {
                    deleteFileAndDir(itemPath);
                } else {
                    // 删除文件
                    _ftp.delete(itemPath, (err) => {
                        if (err) {
                            console.error('删除文件出错：', err);
                        } else {
                            console.log('成功删除文件：', itemPath);
                        }
                    });
                }
            });

            // 删除空文件夹
            _ftp.rmdir(remotePath, (err) => {
                if (err) {
                    console.error('删除文件夹出错：', err);
                } else {
                    console.log('成功删除文件夹：', remotePath);
                }
            });
        });


    }

    // 连接到 FTP 服务器
    await new Promise((resolve, reject) => {
        _ftp.connect(ftpConfig);
        _ftp.on('ready', () => {
            deleteFileAndDir(remotePath);
            resolve();
        });

        _ftp.on('error', reject);
    });
    // 断开连接
    _ftp.end();

}




export {
    connection,
    close,
    list,
    cwd,
    pwd,
    uploadFiles,
    uploadFiles2,
    uploadSingleFile,
    uploadSingleFiles,
    download,
    downloadFiles,
    downloadRecursive,
    deleteFolderAndFiles

};
